package com.cc.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cc.blog.entity.*;
import com.cc.blog.mapper.ArticleBodyMapper;
import com.cc.blog.mapper.ArticleMapper;
import com.cc.blog.mapper.ArticleTagMapper;
import com.cc.blog.service.*;
import com.cc.blog.utils.UserThreadLocal;
import com.cc.blog.vo.*;
import com.cc.blog.vo.params.ArticleParam;
import com.cc.blog.vo.params.PageParams;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private TagService tagService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ArticleBodyMapper articleBodyMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ThreadService threadService;

    @Autowired
    private ArticleTagMapper articleTagMapper;

    /**
     * 分页查询数据库表
     * @param pageParams
     * @return
     */
   /* @Override
    public Result articeList(PageParams pageParams) {
        //1.page对象
        //2.wrapper查询条件
        //3.selectPage
        Page<Article> page = new Page<>(pageParams.getPage(),pageParams.getPageSize());
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        //先置顶排序，再按日期倒序排
        queryWrapper.orderByDesc(Article::getWeight,Article::getCreateDate);
        //查询文章的参数 加上分类id，判断不为空 加上分类条件
        if (pageParams.getCategoryId() != null) {
            queryWrapper.eq(Article::getCategoryId,pageParams.getCategoryId());
        }
        //一个文章可能对应多个标签
        if (pageParams.getTagId() != null){
            LambdaQueryWrapper<ArticleTag> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(ArticleTag::getTagId,pageParams.getTagId());
            List<ArticleTag> articleTags = articleTagMapper.selectList(lambdaQueryWrapper);
            //将获取出来的数组放到一个long型的数组
            List<Long> list = new ArrayList<>();
            for (ArticleTag tag:articleTags){
                list.add(tag.getArticleId());
            }
            if (list.size() > 0){
                queryWrapper.in(Article::getId,list);
            }
        }
        Page<Article> articlePage = articleMapper.selectPage(page, queryWrapper);
        List<Article> records = articlePage.getRecords();
        //要将article转成articleVo
        List<ArticleVo> articleVoList = copyList(records,true,true);
        return Result.success(articleVoList);
    }*/

    /**
     * 文章归档中mp不支持函数，需自定义sql
     *
     */
    @Override
    public Result articeList(PageParams pageParams){
        Page<Article> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());
        IPage<Article> articleIPage = articleMapper.listArchive(page,pageParams.getCategoryId(),pageParams.getTagId(),pageParams.getYear(),pageParams.getMonth());
        return Result.success(copyList(articleIPage.getRecords(),true,true));
    }

    @Override
    public Result hotArtice(int limit) {
        //select id,title from ms_article order by view_counts desc limit 5
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Article::getViewCounts)
                .select(Article::getId,Article::getTitle)
                .last("limit " + limit);

        List<Article> articleList = articleMapper.selectList(queryWrapper);
        //注意返回vo对象
        return Result.success(copyList(articleList,false,false));
    }

    @Override
    public Result newArticle(int limit) {
        //排序由阅读量转成日期
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Article::getCreateDate)
                .select(Article::getId,Article::getTitle)
                .last("limit " + limit);

        List<Article> articleList = articleMapper.selectList(queryWrapper);
        //注意返回vo对象
        return Result.success(copyList(articleList,false,false));
    }

    @Override
    public Result listArchives() {
        //要将毫秒数转成秒数
        //SELECT YEAR(FROM_UNIXTIME(create_date/1000)) AS year,
        // MONTH(FROM_UNIXTIME(create_date/1000)) as month,
        // count(*) as count FROM ms_article GROUP BY year,month
        List<ArchivesDo> archivesDoList =  articleMapper.listArchives();
        return Result.success(archivesDoList);
    }

    @Override
    public Result findArticleById(Long id) {
        Article article = articleMapper.selectById(id);
        //后端500，没有id=14055916999732707300这个对应的文章
        if (article == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "没有这篇文章");
        }
        //多线程记录数量
        threadService.updateViewCount(articleMapper,article);

        return Result.success(copy(article,true,true,true,true));
    }

    @Override
    public Result publish(ArticleParam articleParam) {
        SysUser sysUser = UserThreadLocal.get();
        Article article = new Article();
        article.setAuthorId(sysUser.getId());
        article.setCategoryId(Long.parseLong(articleParam.getCategory().getId()));
        article.setSummary(articleParam.getSummary());
        article.setTitle(articleParam.getTitle());
        article.setCreateDate(System.currentTimeMillis());
        article.setCommentCounts(0);
        article.setViewCounts(0);
        article.setBodyId(-1L);
        article.setWeight(Article.Article_Common);
        articleMapper.insert(article);

        /**
         * 标签
         */
        List<TagVo> tags = articleParam.getTags();
        if (tags != null){
            for (TagVo t : tags) {
                ArticleTag tag = new ArticleTag();
                tag.setTagId(Long.parseLong(t.getId()));
                //取文章的id
                tag.setArticleId(article.getId());
                articleTagMapper.insert(tag);
            }
        }

        /**
         * 文章内容
         */
        ArticleBody articleBody = new ArticleBody();
        articleBody.setContent(articleParam.getBody().getContent());
        articleBody.setContentHtml(articleParam.getBody().getContentHtml());
        articleBody.setArticleId(article.getId());
        articleBodyMapper.insert(articleBody);

        /**
         * 文章获取文章内容id
         */
        article.setBodyId(articleBody.getId());

        /**
         * 更新文章
         */
        articleMapper.updateById(article);

        /**
         * 返回文章id
         */
        ArticleVo articleVo = new ArticleVo();
        articleVo.setId(String.valueOf(article.getId()));
        return Result.success(articleVo);
    }


    private List<ArticleVo> copyList(List<Article> records,boolean isTag,boolean isAuthor){
        List<ArticleVo> list = new ArrayList<>();
        for (Article record:records) {
            list.add(copy(record,isTag,isAuthor));
        }
        return list;
    }

    private ArticleVo copy(Article article,boolean isTag,boolean isAuthor){
        ArticleVo articleVo = new ArticleVo();
        articleVo.setId(String.valueOf(article.getId()));
        BeanUtils.copyProperties(article,articleVo);
        articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH-mm"));
        if (isTag){
            articleVo.setTags(tagService.findTagsByArticleId(article.getId()));
        }
        if (isAuthor){
            articleVo.setAuthor(sysUserService.findUserById(article.getAuthorId()).getNickname());
        }
        return articleVo;
    }
    //使用方法重载
    private ArticleVo copy(Article article,boolean isTag,boolean isAuthor,boolean isBody,boolean isCategory){
        ArticleVo articleVo = new ArticleVo();

        //id精度处理
//        articleVo.setId(article.getId().toString());
        //防止空指针异常
        articleVo.setId(String.valueOf(article.getId()));
        BeanUtils.copyProperties(article,articleVo);
        //数据库中文章时间存的是时间戳
        articleVo.setCreateDate(new DateTime(article.getCreateDate()).toString("yyyy-MM-dd HH:mm"));
        //接下来对四个属性进行填充
        if (isTag) {
            Long articleId = article.getId();
            articleVo.setTags(tagService.findTagsByArticleId(articleId));
        }
        if (isAuthor){
            //如果有作者，获取昵称
            Long authorId = article.getAuthorId();
            articleVo.setAuthor(sysUserService.findUserById(authorId).getNickname());
        }
        if (isBody) {
            articleVo.setBody(findArticleBody(article.getId()));
        }
        if (isCategory) {
            articleVo.setCategory(findArticleCategory(article.getId()));
        }
        return articleVo;
    }

    private ArticleBodyVo findArticleBody(Long id) {
        LambdaQueryWrapper<ArticleBody> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(ArticleBody::getArticleId,id);
        ArticleBodyVo articleBodyVo = new ArticleBodyVo();
        articleBodyVo.setContent(articleBodyMapper.selectOne(queryWrapper).getContent());
        return articleBodyVo;
    }

    private CategoryVo findArticleCategory(Long id){
        return categoryService.findCategoryById(id);
    }
}
